package com.matthewmadson.util.search.yahooboss;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Iterator;
import java.util.List;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.google.common.collect.Lists;

public class YBWebQueryResultSet
	implements Iterator<YBWebQueryResult>, Iterable<YBWebQueryResult>
{
	private String request;
	private long currentTotalOffset;
	private int currentListOffset;
	private YBWebQueryMetadata metadata;
	private List<YBWebQueryResult> currentResults;
	
	public YBWebQueryResultSet(final String request) 
	throws IOException, JSONException
	{
		this.request = request;
		this.currentListOffset = 0;
		this.metadata = new YBWebQueryMetadata();
		this.processNextPage();
	}
	
	private boolean processNextPage() 
	throws IOException, JSONException 
	{
		this.currentResults = Lists.newArrayList();
		URL requestURL = new URL(request);
		BufferedReader br = new BufferedReader(new InputStreamReader(requestURL.openStream()));
		String line = null;
		
		StringBuilder jsonResponse = new StringBuilder();
		while((line = br.readLine()) != null)
			jsonResponse.append(line);
		
		JSONObject json = new JSONObject(jsonResponse.toString());
		JSONObject response = json.getJSONObject("ysearchresponse");
		
		this.metadata.setTotalHits(response.getLong("totalhits"));
		this.metadata.setCount(response.getLong("count"));
		this.metadata.setStart(response.getLong("start"));
		this.metadata.setNextPage(response.getString("nextpage"));
		this.metadata.setResponseCode(response.getInt("responsecode"));
		this.metadata.setDeepHits(response.getLong("deephits"));

		this.request = this.request.replace("start="+this.metadata.getStart(), "start="+(this.metadata.getStart()+this.metadata.getCount()));
		this.currentTotalOffset = this.metadata.getStart();

		JSONArray results = response.getJSONArray("resultset_web");
		
		for(int i = 0; i < results.length(); i++)
		{
			JSONObject jsonResult = results.getJSONObject(i);
			YBWebQueryResult result = new YBWebQueryResult();
			result.setAbstract(jsonResult.getString("abstract"));
			result.setClickURL(jsonResult.getString("clickurl"));
			result.setDate(jsonResult.getString("date"));
			result.setDispURL(jsonResult.getString("dispurl"));
			result.setSize(jsonResult.getLong("size"));
			result.setTitle(jsonResult.getString("title"));
			result.setURL(jsonResult.getString("url"));
			result.setOffset(this.currentTotalOffset+i);
			this.currentResults.add(result);
		}

		return this.currentTotalOffset < this.metadata.getTotalHits();
	}
	
	public YBWebQueryMetadata getMetadata() 
	throws IOException, JSONException
	{
		return this.metadata;
	}

	public boolean hasNext()
	{
		if(this.currentListOffset < this.currentResults.size())
			return true;
		else
		{
			try
			{
				this.currentListOffset = 0;
				return processNextPage();
			}
			catch(Exception e)
			{
				throw new RuntimeException(e);
			}
		}
	}

	public YBWebQueryResult next()
	{
		return this.currentResults.get(this.currentListOffset++);
	}

	public void remove()
	{
		throw new UnsupportedOperationException();
	}

	public Iterator<YBWebQueryResult> iterator()
	{
		return this;
	}
}
